//==============================================================================
//
// File: MainWindow.cpp
// Project: Browser
// Author(s): Matthias Van Eeghem (matthias@van-eeghem.com)
// License: See LICENSE in root directory
//
// The entry point for the visual part of the application.
//
//==============================================================================

#include "Constants.h"
#include "ui_MainWindow.h"
#include "CBrowser.h"
#include "CFavoriteList.h"
#include "CInternetList.h"
#include "Forms/AddFavorite/AddFavoriteDialog.h"
#include "Forms/ShowSettings/SettingsDialog.h"
#include "Forms/ServerInfo/ServerInfoDialog.h"

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    // Make sure the window isn't resizable
    this->setFixedSize(673, 454);

    // Initialise the favorite and internet treeview
    CFavoriteList::InitialiseFavoritesList(this);
    CInternetList::InitialiseInternetList(this);

    // Initialise the browser's settings
    CBrowser::InitialiseSettings(this);

    // Load all favorites
    CFavoriteList::LoadFavorites();

    // Create a new NetworkManager
    m_pNetworkManager = new QNetworkAccessManager(this);

    // Call onInternetListReceived() when the browser has finished downloading the internet list
    connect(m_pNetworkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(onNetworkReplyReceived(QNetworkReply*)));

    // Request the masterlist
    m_pNetworkManager->get(QNetworkRequest(QUrl(QString(MASTERLIST_HOST) + QString(INTERNETLIST_PATH))));
}

// Called when the user hits "Add favorite" under the Servers menu item
void MainWindow::on_actionAdd_favorite_triggered()
{
    AddFavorite AddFavoriteDialog(this, this);
    AddFavoriteDialog.exec();
}

// Called when the user hits "Show settings" under the Settings menu item
void MainWindow::on_actionShow_settings_triggered()
{
    ShowSettings ShowSettingsDialog(this);
    ShowSettingsDialog.exec();
}

// Called when the user hits "Delete favorite" under the Servers menu item
void MainWindow::on_actionDelete_favorite_triggered()
{
    if(ui->TabWidget->currentIndex() == TAB_FAVORITELIST && ui->FavoritesList->currentIndex().row() != -1)
    {
        CFavoriteList::RemoveCurrentlySelectedItem();
    }
}

// Called when the user clicks "Add to favorites" in the custom context menu in the internet list
void MainWindow::on_actionAddToFavoriteList_triggered()
{
    // Make sure we have a valid treeviewitem selected
    if(ui->InternetList->currentIndex().row() != -1)
    {
        // Get the selected IP
        QString ServerIP = ui->InternetList->currentItem()->text(COLUMN_IP);

        // Make sure the IP isn't added already to the favorite list
        if(CFavoriteList::DoesFavoriteExist(ServerIP))
        {
            QMessageBox::information(this, "Invalid IP", "That IP address has already been added to your favorites list.");
            return;
        }

        // Add the favorite server
        CFavoriteList::AddFavorite(ServerIP, true);

        // Request information about this server
        m_pNetworkManager->get(QNetworkRequest(QUrl(QString(MASTERLIST_HOST) + QString(SERVERINFO_PATH) + ServerIP)));

        // Select the favorite tab
        ui->TabWidget->setCurrentIndex(TAB_FAVORITELIST);
    }
}

// Called when the user triggers the "Refresh" action
void MainWindow::on_actionRefresh_internet_list_triggered()
{
    // Clear both the internet TreeView and QList
    m_lInternetList.clear();
    ui->InternetList->clear();

    // Re-request the masterlist
    m_pNetworkManager->get(QNetworkRequest(QUrl(QString(MASTERLIST_HOST) + QString(INTERNETLIST_PATH))));
}

// Called when the user triggers the "Connect" action
void MainWindow::on_actionConnect_triggered()
{
    // Get the playername
    QSettings settings;
    QString PlayerName = settings.value("PlayerName").value<QString>();

    CServer SelectedServer;
    int iSelectedIndex;

    // Is the "Favorites" tab selected?
    if(ui->TabWidget->currentIndex() == TAB_FAVORITELIST)
    {
        iSelectedIndex = ui->FavoritesList->currentIndex().row();

        // Make sure a valid server is selected
        if(iSelectedIndex != -1)
        {
            // Get the CServer object
            SelectedServer = m_lFavoritesList.at(iSelectedIndex);
            // Launch the game
            CBrowser::LaunchGame(SelectedServer.m_sIP, SelectedServer.m_sPort, PlayerName);
        }
    }

    // Is the "Internet" tab selected?
    if(ui->TabWidget->currentIndex() == TAB_INTERNETLIST)
    {
        iSelectedIndex = ui->InternetList->currentIndex().row();

        // Make sure a valid server is selected
        if(iSelectedIndex != -1)
        {
            // Get the CServer object
            SelectedServer = m_lInternetList.at(iSelectedIndex);
            // Launch the game
            CBrowser::LaunchGame(SelectedServer.m_sIP, SelectedServer.m_sPort, PlayerName);
        }
    }
}

// Called when the user double clicks an item in the favorites TreeView
void MainWindow::on_FavoritesList_doubleClicked(const QModelIndex &)
{
    int iSelectedIndex = ui->FavoritesList->currentIndex().row();

    // Is the server valid?
    if(iSelectedIndex != -1)
    {
        CServer Server = m_lFavoritesList.at(iSelectedIndex);

        // Show more information about the server
        ServerInfo ServerInfoDialog(this, Server);
        ServerInfoDialog.exec();
    }
}

// Called when the user double clicks an item in the internet TreeView
void MainWindow::on_InternetList_doubleClicked(const QModelIndex &)
{
    int iSelectedIndex = ui->InternetList->currentIndex().row();

    // Is the server valid?
    if(iSelectedIndex != -1)
    {
        CServer Server = m_lInternetList.at(iSelectedIndex);

        // Show more information about the server
        ServerInfo ServerInfoDialog(this, Server);
        ServerInfoDialog.exec();
    }
}

// Called when the user clicks an item in the favorites TreeView
void MainWindow::on_FavoritesList_clicked(const QModelIndex &)
{
    m_pNetworkManager->get(QNetworkRequest(QUrl(QString(MASTERLIST_HOST) + QString(SERVERINFO_PATH) + ui->FavoritesList->currentItem()->text(3))));
}

// Called when the user clicks an item in the internet TreeView
void MainWindow::on_InternetList_clicked(const QModelIndex &)
{
    m_pNetworkManager->get(QNetworkRequest(QUrl(QString(MASTERLIST_HOST) + QString(SERVERINFO_PATH) + ui->InternetList->currentItem()->text(3))));
}

// Called when the application receives a HTTP reply from an earlier sent request
void MainWindow::onNetworkReplyReceived(QNetworkReply *pReply)
{
    // Read the contents of the reply
    QString sContents(pReply->readAll());

    // The reply is the reply to the masterlists request
    if(pReply->url().toString() == (QString(MASTERLIST_HOST) + QString(INTERNETLIST_PATH)))
    {
        CInternetList::HandleInternetListReply(sContents);
    }

    // Otherwise the reply is the reply to a request for more information about a specific server
    else
    {
        // Make sure GetServerInfo.php actually output something
        if(sContents.length() > 0)
        {
            HandleValidServerInfoReply(sContents);
        }
        else
        {
            HandlesInvalidServerInfoReply(pReply->url());
        }
    }
}

// Handles a valid reply to an earlier request for an update of a specific server
void MainWindow::HandleValidServerInfoReply(QString sContents)
{
    // Split the server IP and server port from the IP
    QStringList ServerInformation = sContents.split(SERVERDATA_SEPERATOR);
    QString ServerIP = ServerInformation[0].split(':')[0];
    QString ServerPort = ServerInformation[0].split(':')[1];

    // Setup the CServer object from the received information
    CServer Server;
    Server.m_sIP = ServerIP;
    Server.m_sPort = ServerPort;
    Server.m_sVersion = ServerInformation[1];
    Server.m_sHostname = ServerInformation[2];
    Server.m_iPlayers = ServerInformation[3].toInt();
    Server.m_iMaxPlayers = ServerInformation[4].toInt();

    // The request for more information could come either from the favorites list or the internet list
    // Loop through all the favorites
    for(int i = 0; i < m_lFavoritesList.size(); i++)
    {
        // Check if we have a match of the IP and port for any of the favorite servers
        if(m_lFavoritesList.at(i).m_sIP == Server.m_sIP && m_lFavoritesList.at(i).m_sPort == Server.m_sPort)
        {
            // Replace the (invalid) CServer object by a valid CServer object
            m_lFavoritesList.replace(i, Server);

            // Update the TreeView item
            ui->FavoritesList->topLevelItem(i)->setText(COLUMN_HOSTNAME, Server.m_sHostname);
            ui->FavoritesList->topLevelItem(i)->setText(COLUMN_PLAYERS, ServerInformation[3] + "/" + ServerInformation[4]);
            ui->FavoritesList->topLevelItem(i)->setText(COLUMN_VERSION, Server.m_sVersion);
        }
    }

    // Loop through all the internet servers
    for(int i = 0; i < m_lInternetList.size(); i++)
    {
        // Check if we have a match of the IP and port for any of the favorite servers
        if(m_lInternetList.at(i).m_sIP == ServerIP && m_lInternetList.at(i).m_sPort == Server.m_sPort )
        {
            // Replace the (invalid) CServer object by a valid CServer object
            m_lInternetList.replace(i, Server);

            // Update the TreeView item
            ui->InternetList->topLevelItem(i)->setText(COLUMN_HOSTNAME, Server.m_sHostname);
            ui->InternetList->topLevelItem(i)->setText(COLUMN_PLAYERS, ServerInformation[3] + "/" + ServerInformation[4]);
            ui->InternetList->topLevelItem(i)->setText(COLUMN_VERSION, Server.m_sVersion);
        }
    }
}

// Handles an invalid reply to an earlier request for an update of a specific server
void MainWindow::HandlesInvalidServerInfoReply(QUrl qUrl)
{
    // Get the IP from the original URL request
    QString sIP = qUrl.queryItems().at(0).second;
    QStringList ServerInfo = sIP.split(':');

    // Loop through all favorites so we can find the server
    for(int i = 0; i < m_lFavoritesList.size(); i++)
    {
        // Check if we have a match of the IP and port for any of the favorite servers
        if(m_lFavoritesList.at(i).m_sIP == ServerInfo[0] && m_lFavoritesList.at(i).m_sPort == ServerInfo[1])
        {
            // Create an invalid CServer object
            CServer InvalidServer;
            InvalidServer.m_sIP = ServerInfo[0];
            InvalidServer.m_sPort = ServerInfo[1];
            InvalidServer.m_sVersion = "No version found";
            InvalidServer.m_sHostname = sIP;
            InvalidServer.m_iPlayers = 0;
            InvalidServer.m_iMaxPlayers = 0;

            // Replace the (valid) CServer object by an invalid CServer object
            m_lFavoritesList.replace(i, InvalidServer);

            // Update the TreeView item
            ui->FavoritesList->topLevelItem(i)->setText(COLUMN_HOSTNAME, "No hostname found");
            ui->FavoritesList->topLevelItem(i)->setText(COLUMN_PLAYERS, "0/0");
            ui->FavoritesList->topLevelItem(i)->setText(COLUMN_VERSION, "No version found");
        }
    }

    // Loop through all internet servers so we can find the server we need to remove
    for(int i = 0; i < m_lInternetList.size(); i++)
    {
        // Check if we have a match of the IP and port for any of the internet servers
        if(m_lInternetList.at(i).m_sIP == ServerInfo[0] && m_lInternetList.at(i).m_sPort == ServerInfo[1])
        {
            m_lInternetList.removeAt(i);
            ui->InternetList->model()->removeRow(i);
        }
    }
}

// The destructor
MainWindow::~MainWindow()
{
    delete ui;
}
